package it.fuzzylogics.fuzzywidgetsLibrary.client.FuzzyVerticalTable;

import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Widget;
import it.fuzzylogics.fuzzywidgetsLibrary.client.FuzzyListeners.FClickListener;
import it.fuzzylogics.fuzzywidgetsLibrary.client.FuzzyListeners.FClickListenerHandler;
import it.fuzzylogics.fuzzywidgetsLibrary.client.FuzzyListeners.FMouseListener;
import it.fuzzylogics.fuzzywidgetsLibrary.client.FuzzyListeners.FMouseListenerHandler;
import it.fuzzylogics.fuzzywidgetsLibrary.client.FuzzyPNGImage.FPNGImage;


abstract class FColumn extends AbsolutePanel {

    FlexTable flextable;
    FPNGImage upArrow = null, downArrow = null;
    AbsolutePanel flexContainer, cursorContainer, cursor;
    FColumn me = this;
   public  Timer upTimer,downTimer;
    public boolean block = false;

    int width, height;

    int itemHeight = 20;
    int rowSpacing = 5;
    int arrowWidth = 15, arrowHeight = 15;
    int flexSpacing = 2;

    int scrollPosition = 0;

    public FColumn() {


        initGui();

    }

    private void initGui() {

        cursorContainer = new AbsolutePanel();
        cursor = new AbsolutePanel();
        cursorContainer.setStyleName("FVerticalTable-CursorContainer");
        cursor.setStyleName("FVerticalTable-Cursor");

        flextable = new FlexTable();
        flexContainer = new AbsolutePanel();

        upArrow = new FPNGImage("fuzzyWidgetsImages/sfera.png", arrowWidth, arrowHeight);
        downArrow = new FPNGImage("fuzzyWidgetsImages/sfera.png", arrowWidth, arrowHeight);

        addArrowListeners();

        add(cursorContainer);
        cursorContainer.add(cursor, 0, 0);

        add(flexContainer);
        flexContainer.add(flextable);

        flextable.setCellPadding(0);
        flextable.setCellSpacing(0);

        add(upArrow);
        add(downArrow);

    }

    private void addArrowListeners() {


       upTimer = new Timer()
        {




            public void run() {
                if (block) return;

                int offset = (rowSpacing + itemHeight);
                if (-scrollPosition < rowSpacing + itemHeight) {

                    flexContainer.setWidgetPosition(flextable, 0, 0);
                    scrollPosition = 0;
                    setCursorPosition();
                    onScroll(scrollPosition);
                    return;
                }


                if (scrollPosition < 0) {
                    flexContainer.setWidgetPosition(flextable, 0, scrollPosition + offset);
                    scrollPosition += offset;
                    setCursorPosition();
                    onScroll(scrollPosition);

                } else {
                    cancel();
                }


            }


        };

       downTimer = new Timer()
        {

      



            public void run() {
                if (block) return;

                int offset = (rowSpacing + itemHeight);
                //  System.out.println(flextable.getOffsetHeight()+scrollPosition-flexContainer.getOffsetHeight());
                if (flextable.getOffsetHeight() + scrollPosition - flexContainer.getOffsetHeight() < rowSpacing + itemHeight) {
                    // System.out.println("entrato");
                    offset = flextable.getOffsetHeight() + scrollPosition - flexContainer.getOffsetHeight();
                }

                if (flexContainer.getOffsetHeight() < flextable.getOffsetHeight() && -(scrollPosition) < flextable.getOffsetHeight() - flexContainer.getOffsetHeight()) {
                    flexContainer.setWidgetPosition(flextable, 0, scrollPosition - offset);
                    scrollPosition -= offset;
                    setCursorPosition();
                    onScroll(scrollPosition);

                } else {
                    cancel();
                }

            }
        };

        FMouseListener.setMouseEvent(upArrow.getElement(), new FMouseListenerHandler() {

            public void onClick() {
            }

            public void onMouseDown(int x, int y) {

            }

            public void onMouseEnter() {

                upTimer.run();
                upTimer.scheduleRepeating(100);
            }

            public void onMouseLeave() {
                upTimer.cancel();
            }

            public void onMouseUp(int x, int y) {

            }

            public void onMouseWheelUp(int intensity) {
            }

            public void onMouseWheelDown(int intensity) {
            }

            public void onMouseMove(int x, int y) {
            }
        });

        FMouseListener.setMouseEvent(downArrow.getElement(), new FMouseListenerHandler() {

            public void onClick() {
            }

            public void onMouseDown(int x, int y) {

            }

            public void onMouseEnter() {


                downTimer.run();
                downTimer.scheduleRepeating(100);
            }

            public void onMouseLeave() {
                downTimer.cancel();
            }

            public void onMouseUp(int x, int y) {

            }

            public void onMouseWheelUp(int intensity) {
            }

            public void onMouseWheelDown(int intensity) {
            }

            public void onMouseMove(int x, int y) {
            }
        });
    }

    public void setPixelSize(int w, int h) {

        super.setPixelSize(w, h);

        width = w;
        height = h;

        updateGui();
    }

    public void updateGui() {

        setWidgetPosition(cursorContainer, width - 2, arrowHeight + flexSpacing + 2);
        cursorContainer.setPixelSize(2, height - (2 * arrowHeight) - (2 * flexSpacing) - 4);


        double flexH = ((flextable.getRowCount() - 1) * rowSpacing) + (flextable.getRowCount() * itemHeight);
        double flexContainerH = (height - (2 * arrowHeight) - (2 * flexSpacing) - 4);

        cursor.setPixelSize(2, (int) (flexContainerH * flexContainerH / flexH));

        setCursorPosition();

        setWidgetPosition(flexContainer, 0, arrowHeight + flexSpacing + 2);
        setWidgetPosition(upArrow, (width - arrowWidth) / 2, 2);
        setWidgetPosition(downArrow, (width - arrowWidth) / 2, height - arrowHeight - 2);

        upArrow.setPixelSize(arrowWidth, arrowHeight);
        downArrow.setPixelSize(arrowWidth, arrowHeight);


        flexContainer.setPixelSize(width - 3, height - (2 * arrowHeight) - (2 * flexSpacing) - 4);

        if (!block) {
            flextable.setPixelSize(width, ((flextable.getRowCount() - 1) * rowSpacing) + (flextable.getRowCount() * itemHeight));


            for (int i = 0; i < flextable.getRowCount(); i++)
                flextable.getWidget(i, 0).setPixelSize(width, itemHeight);

        }
    }

    public void addItem(final Widget w) {

        w.setStyleName("FVerticalTable-item");
        flextable.setWidget(flextable.getRowCount(), 0, w);
        final int index = flextable.getRowCount();
        FClickListener.setClickEvent(w.getElement(), new FClickListenerHandler() {

            public void onClick() {
                selectItem(index - 1);
            }

        });
        w.setPixelSize(width, itemHeight);
    }

    public void removeItem(int index) {
        flextable.removeRow(index);
        updateGui();

    }


    public void setItemHeight(int itemHeight) {
        this.itemHeight = itemHeight;
        for (int i = 0; i < flextable.getRowCount(); i++)
            flextable.getWidget(i, 0).setPixelSize(width, itemHeight);


    }

    public Widget getItem(int index) {
        return flextable.getWidget(index, 0);
    }

    public void setScrollPosition(int scrollPosition) {
        flexContainer.setWidgetPosition(flextable, 0, scrollPosition);
        this.scrollPosition = scrollPosition;
        setCursorPosition();

    }

    public void setArrowWidgetsUrl(String upArrowUrl, String downArrowUrl) {
        upArrow.setUrl(upArrowUrl, arrowWidth, arrowHeight);
        downArrow.setUrl(downArrowUrl, arrowWidth, arrowHeight);
        addArrowListeners();
    }


    public void setRowSpacing(int rowSpacing) {
        this.rowSpacing = rowSpacing;
        updateGui();
    }

    public void setArrowsSize(int width, int height) {
        arrowWidth = width;
        arrowHeight = height;
        updateGui();
    }

    private void setCursorPosition() {

        double flexH = ((flextable.getRowCount() - 1) * rowSpacing) + (flextable.getRowCount() * itemHeight);
        double flexContainerH = (height - (2 * arrowHeight) - (2 * flexSpacing) - 4);
        int cursorPos = (int) (((-scrollPosition) * flexContainerH / flexH));
        try {
            cursorContainer.setWidgetPosition(cursor, 0, cursorPos);
            // System.out.println(cursorPos+" "+flexContainerH+" "+flexH);
        } catch (Exception e) {
        }
    }


    public void ensureVisibleItem(int index) {

        int pos = (rowSpacing * (index) - 1) + (itemHeight * index);
        int flexContainerH = (height - (2 * arrowHeight) - (2 * flexSpacing) - 4);

        //  if(pos>(flexContainerH-scrollPosition) )
        // {


        int visibleItemsNum = flexContainerH / ((rowSpacing - 1) + itemHeight);


        if (index > (flextable.getRowCount() - visibleItemsNum)) {
            pos = (rowSpacing * ((flextable.getRowCount() - visibleItemsNum)) - 1) + (itemHeight * (flextable.getRowCount() - visibleItemsNum));
            setScrollPosition(-pos/*+offset*/);

            onScroll(-pos/*+offset*/);
        } else if (index < visibleItemsNum) {
            setScrollPosition(0);

            onScroll(0);
        } else {
            visibleItemsNum = visibleItemsNum / 2;
            int offset = (rowSpacing * (visibleItemsNum)) + (itemHeight * visibleItemsNum);
            setScrollPosition(-pos + offset);

            onScroll(-pos + offset);

        }

        //}


    }


    abstract public void onScroll(int scrollPosition);

    abstract public void selectItem(int index);


}
